{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "3265466e-cf51-4dc4-a4d7-79a5682a18cb",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "加载docx\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[Document(metadata={'source': 'kecheng/example/fake.docx'}, page_content='一、公司基本信息\\n\\n名称：宏图科技发展有限公司\\n\\n注册地址：江苏省南京市雨花台区软件大道101号\\n\\n成立日期：2011年5月16日\\n\\n法定代表人：李强\\n\\n注册资本：人民币5000万元\\n\\n员工人数：约200人\\n\\n联系电话：025-88888888\\n\\n电子邮箱：info@hongtutech.cn\\n\\n\\n\\n二、财务状况概述\\n\\n截至2023年第一季度，宏图科技发展有限公司财务状况堪忧，具体情况如下：\\n\\n1. 资产总额：人民币1.2亿元，较上年同期下降30%。\\n\\n2. 负债总额：人民币1.8亿元，较上年同期上升50%，资不抵债。\\n\\n3. 营业收入：人民币3000万元，较上年同期下降60%。\\n\\n4. 净利润：亏损人民币800万元，去年同期为盈利人民币200万元。\\n\\n5. 现金流量：公司现金流量紧张，现金及现金等价物余额为人民币500万元，难以支撑日常运营。\\n\\n6. 存货：存货积压严重，库存商品价值约为人民币400万元，大部分产品滞销。\\n\\n7. 应收账款：应收账款高达人民币600万元，回收难度大，坏账准备不足。\\n\\n\\n\\n三、主营业务及市场状况\\n\\n宏图科技发展有限公司主要从事计算机软件的研发与销售。近年来，由于市场竞争加剧、技术更新换代速度快和管理层决策失误等原因，公司主营业务收入持续下降。目前，公司面临的主要问题有：\\n\\n1. 产品同质化严重，缺乏核心竞争力。\\n\\n2. 新产品开发进度缓慢，未能及时抓住市场需求变化。\\n\\n3. 市场营销策略不当，导致市场份额大幅缩水。\\n\\n4. 行业内新兴企业崛起迅速，原有客户流失严重。\\n\\n\\n\\n四、债权债务情况\\n\\n宏图科技发展有限公司目前面临的债务问题严峻，具体情况如下：\\n\\n1. 银行贷款：公司向多家银行贷款总额达人民币1亿元，部分贷款已逾期未还。\\n\\n2. 供应商欠款：因现金流紧张，公司拖欠供应商货款达人民币300万元。\\n\\n3. 员工工资及社保：由于资金链断裂，公司拖欠员工工资及社保费用共计人民币200万元。\\n\\n4. 其他应付款项：包括税费、租赁费用等其他应付款项累计约人民币100万元。\\n\\n\\n\\n五、资产清单\\n\\n宏图科技发展有限公司目前拥有的主要资产包括：\\n\\n1. 固定资产：公司办公用房和设备原值合计人民币800万元，累计折旧约400万元。\\n\\n2. 无形资产：包括软件著作权、专利权等无形资产原值合计人民币300万元。\\n\\n3. 存货资产：存货包括已完成软件产品和半成品，价值约为人民币400万元。\\n\\n4. 应收账款：主要包括对外销售软件的应收账款合计人民币600万元。\\n\\n\\n\\n六、潜在风险及预警\\n\\n1. 经营风险：由于连续亏损，公司可能面临破产清算的风险。\\n\\n2. 债务风险：负债累累，若短期内无法筹措足够资金偿还债务，可能面临诉讼或资产被查封的风险。\\n\\n3. 市场风险：行业竞争加剧和市场需求不明朗，可能导致公司未来业绩继续恶化。\\n\\n4. 法律风险：因未能按时支付债务和相关费用，可能面临相关法律诉讼或处罚。\\n\\n\\n\\n七、结论与建议\\n\\n综上所述，宏图科技发展有限公司目前处于财务困境之中，若无外部资金注入或业务转型成功，短期内难以扭转局势。对于不良资产收购方来说，在考虑收购宏图科技的相关资产前，建议进行深入的尽职调查，并制定详细的风险控制和资产处置方案。同时，在估值时应充分考虑到公司所面临的各种潜在风险和清收难度。\\n\\n\\n\\n报告撰写日期：2023年4月20日')]"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print(\"加载docx\")\n",
    "#倒入必须的包\n",
    "from langchain.document_loaders import Docx2txtLoader\n",
    "\n",
    "#定义chatdoc\n",
    "class ChatDoc():\n",
    "    def getFile():\n",
    "        #读取文件\n",
    "        loader = Docx2txtLoader(\"kecheng/example/fake.docx\")\n",
    "        text = loader.load()\n",
    "        return text;\n",
    "\n",
    "ChatDoc.getFile()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "6cd9ad90-dd1c-45c3-8c4b-765ebeccb838",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "加载pdf文档\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Ignoring wrong pointing object 6 0 (offset 0)\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[Document(metadata={'producer': 'macOS 版本14.1.1（版号23B81） Quartz PDFContext', 'creator': 'PyPDF', 'creationdate': \"D:20231205083748Z00'00'\", 'moddate': \"D:20231205083748Z00'00'\", 'source': 'kecheng/example/fake.pdf', 'total_pages': 3, 'page': 0, 'page_label': '1'}, page_content='一、公司基本信息 名称：宏图科技发展有限公司 注册地址：江苏省南京市雨花台区软件大道101号 成立日期：2011年5月16日 法定代表人：李强 注册资本：人民币5000万元 员工人数：约200人 联系电话：025-88888888 电子邮箱：info@hongtutech.cn  二、财务状况概述 截至2023年第一季度，宏图科技发展有限公司财务状况堪忧，具体情况如下： 1. 资产总额：人民币1.2亿元，较上年同期下降30%。 2. 负债总额：人民币1.8亿元，较上年同期上升50%，资不抵债。 3. 营业收入：人民币3000万元，较上年同期下降60%。 4. 净利润：亏损人民币800万元，去年同期为盈利人民币200万元。 5. 现金流量：公司现金流量紧张，现金及现金等价物余额为人民币500万元，难以支撑日常运营。 6. 存货： 存货积压严重， 库存商品价值约为人民币400万元， 大部分产品滞销。 7. 应收账款：应收账款高达人民币600万元，回收难度大，坏账准备不足。  三、主营业务及市场状况 宏图科技发展有限公司主要从事计算机软件的研发与销售。近年来，由于市场竞争加剧、技术更新换代速度快和管理层决策失误等原因，公司主营业务收入持续下降。目前，公司面临的主要问题有： 1. 产品同质化严重，缺乏核心竞争力。 2. 新产品开发进度缓慢，未能及时抓住市场需求变化。 3. 市场营销策略不当，导致市场份额大幅缩水。'),\n",
       " Document(metadata={'producer': 'macOS 版本14.1.1（版号23B81） Quartz PDFContext', 'creator': 'PyPDF', 'creationdate': \"D:20231205083748Z00'00'\", 'moddate': \"D:20231205083748Z00'00'\", 'source': 'kecheng/example/fake.pdf', 'total_pages': 3, 'page': 1, 'page_label': '2'}, page_content='4. 行业内新兴企业崛起迅速，原有客户流失严重。  四、债权债务情况 宏图科技发展有限公司目前面临的债务问题严峻，具体情况如下： 1. 银行贷款： 公司向多家银行贷款总额达人民币1亿元， 部分贷款已逾期未还。 2. 供应商欠款：因现金流紧张，公司拖欠供应商货款达人民币300万元。 3. 员工工资及社保：由于资金链断裂，公司拖欠员工工资及社保费用共计人民币200万元。 4. 其他应付款项： 包括税费、 租赁费用等其他应付款项累计约人民币100万元。  五、资产清单 宏图科技发展有限公司目前拥有的主要资产包括： 1. 固定资产：公司办公用房和设备原值合计人民币800万元，累计折旧约400万元。 2. 无形资产：包括软件著作权、专利权等无形资产原值合计人民币300万元。 3. 存货资产：存货包括已完成软件产品和半成品，价值约为人民币400万元。 4. 应收账款：主要包括对外销售软件的应收账款合计人民币600万元。  六、潜在风险及预警 1. 经营风险：由于连续亏损，公司可能面临破产清算的风险。 2. 债务风险：负债累累，若短期内无法筹措足够资金偿还债务，可能面临诉讼或资产被查封的风险。 3. 市场风险：行业竞争加剧和市场需求不明朗，可能导致公司未来业绩继续恶化。 4. 法律风险： 因未能按时支付债务和相关费用， 可能面临相关法律诉讼或处罚。  七、结论与建议 综上所述，宏图科技发展有限公司目前处于财务困境之中，若无外部资金注入或业务转型成功，短期内难以扭转局势。对于不良资产收购方来说，在考虑收购宏'),\n",
       " Document(metadata={'producer': 'macOS 版本14.1.1（版号23B81） Quartz PDFContext', 'creator': 'PyPDF', 'creationdate': \"D:20231205083748Z00'00'\", 'moddate': \"D:20231205083748Z00'00'\", 'source': 'kecheng/example/fake.pdf', 'total_pages': 3, 'page': 2, 'page_label': '3'}, page_content='图科技的相关资产前，建议进行深入的尽职调查，并制定详细的风险控制和资产处置方案。 同时， 在估值时应充分考虑到公司所面临的各种潜在风险和清收难度。  报告撰写日期：2023年4月20日')]"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print(\"加载pdf文档\")\n",
    "#导入必须的包\n",
    "from langchain.document_loaders import PyPDFLoader\n",
    "\n",
    "#定义chatdoc\n",
    "class ChatDoc():\n",
    "    def getFile():\n",
    "        try:\n",
    "            #读取文件\n",
    "            loader = PyPDFLoader(\"kecheng/example/fake.pdf\")\n",
    "            text = loader.load()\n",
    "            return text;\n",
    "        except Exception as e:\n",
    "            print(f\"Error loading files:{e}\")\n",
    "ChatDoc.getFile()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "6eae63b8-ce34-494b-956a-24d2365a3af3",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "加载下excel\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[Document(metadata={'source': 'kecheng/example/fake.xlsx', 'file_directory': 'kecheng/example', 'filename': 'fake.xlsx', 'last_modified': '2024-04-12T12:05:13', 'page_name': 'Sheet1', 'page_number': 1, 'text_as_html': '<table><tr><td>名称</td><td>宏图科技发展有限公司</td></tr><tr><td>注册地址</td><td>江苏省南京市雨花台区软件大道101号</td></tr><tr><td>成立日期</td><td>40679</td></tr><tr><td>法定代表人</td><td>李强</td></tr><tr><td>注册资本</td><td>人民币5000万元</td></tr><tr><td>员工人数</td><td>约200人</td></tr><tr><td>联系电话</td><td>025-88888888</td></tr><tr><td>电子邮箱</td><td>info@hongtutech.cn</td></tr><tr><td>资产总额</td><td>人民币1.2亿元，较上年同期下降30%</td></tr><tr><td>负债总额</td><td>人民币1.8亿元，较上年同期上升50%，资不抵债</td></tr><tr><td>营业收入</td><td>人民币3000万元，较上年同期下降60%</td></tr><tr><td>净利润</td><td>亏损人民币800万元，去年同期为盈利人民币200万元</td></tr><tr><td>现金流量</td><td>公司现金流量紧张，现金及现金等价物余额为人民币500万元，难以支撑日常运营</td></tr></table>', 'languages': ['zho', 'kor'], 'filetype': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'category': 'Table', 'element_id': '7ed30bdc7ad64071dae72ac7a379911a'}, page_content='名称 宏图科技发展有限公司 注册地址 江苏省南京市雨花台区软件大道101号 成立日期 40679 法定代表人 李强 注册资本 人民币5000万元 员工人数 约200人 联系电话 025-88888888 电子邮箱 info@hongtutech.cn 资产总额 人民币1.2亿元，较上年同期下降30% 负债总额 人民币1.8亿元，较上年同期上升50%，资不抵债 营业收入 人民币3000万元，较上年同期下降60% 净利润 亏损人民币800万元，去年同期为盈利人民币200万元 现金流量 公司现金流量紧张，现金及现金等价物余额为人民币500万元，难以支撑日常运营')]"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print(\"加载下excel\")\n",
    "#导入必须的包\n",
    "from langchain.document_loaders import UnstructuredExcelLoader\n",
    "\n",
    "#定义chatdoc\n",
    "class ChatDoc():\n",
    "    def getFile():\n",
    "        try:\n",
    "            #读取文件\n",
    "            loader = UnstructuredExcelLoader(\"kecheng/example/fake.xlsx\",mode=\"elements\")\n",
    "            text = loader.load()\n",
    "            return text;\n",
    "        except Exception as e:\n",
    "            print(f\"Error loading files:{e}\")\n",
    "ChatDoc.getFile()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "58e353c8-c900-4eed-9126-0d981db8965f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "整合优化，动态加载三种文件格式,增加了文本切割\n",
      "[Document(metadata={'source': 'kecheng/example/fake.xlsx'}, page_content='名称 宏图科技发展有限公司 注册地址 江苏省南京市雨花台区软件大道101号 成立日期 40679 法定代表人 李强 注册资本 人民币5000万元 员工人数 约200人 联系电话 025-88888888 电子邮箱 info@hongtutech.cn 资产总额 人民币1.2亿元，较上年同期下降30% 负债总额 人民币1.8亿元，较上年同期上升50%，资不抵债 营业收入 人民币3000万元，较上年同期下降60% 净利润 亏损人民币800万元，去年同期为盈利人民币200万元 现金流量 公司现金流量紧张，现金及现金等价物余额为人民币500万元，难以支撑日常运营')]\n"
     ]
    }
   ],
   "source": [
    "print(\"整合优化，动态加载三种文件格式,增加了文本切割\")\n",
    "#导入必须的包\n",
    "from langchain.document_loaders import UnstructuredExcelLoader,Docx2txtLoader,PyPDFLoader\n",
    "from langchain.text_splitter import  CharacterTextSplitter\n",
    "\n",
    "\n",
    "#定义chatdoc\n",
    "class ChatDoc():\n",
    "    def __init__(self):\n",
    "        self.doc = None\n",
    "        self.splitText = [] #分割后的文本\n",
    "\n",
    "    def getFile(self):\n",
    "        doc = self.doc\n",
    "        loaders = {\n",
    "            \"docx\":Docx2txtLoader,\n",
    "            \"pdf\":PyPDFLoader,\n",
    "            \"xlsx\":UnstructuredExcelLoader,\n",
    "        }\n",
    "        file_extension = doc.split(\".\")[-1]\n",
    "        loader_class = loaders.get(file_extension)\n",
    "        if loader_class:\n",
    "            try:\n",
    "                loader = loader_class(doc)\n",
    "                text = loader.load()\n",
    "                return text\n",
    "            except Exception as e: \n",
    "                print(f\"Error loading {file_extension} files:{e}\") \n",
    "        else:\n",
    "             print(f\"Unsupported file extension: {file_extension}\")\n",
    "             return  None \n",
    "\n",
    "    #处理文档的函数\n",
    "    def splitSentences(self):\n",
    "        full_text = self.getFile() #获取文档内容\n",
    "        if full_text != None:\n",
    "            #对文档进行分割\n",
    "            text_split = CharacterTextSplitter(\n",
    "                chunk_size=150,\n",
    "                chunk_overlap=20,\n",
    "            )\n",
    "            texts = text_split.split_documents(full_text)\n",
    "            self.splitText = texts\n",
    "\n",
    "chat_doc = ChatDoc()\n",
    "chat_doc.doc = \"kecheng/example/fake.xlsx\"\n",
    "chat_doc.splitSentences()\n",
    "print(chat_doc.splitText)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "e314bf28-4a91-44b3-aba7-87062ba89d97",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "向量化与存储索引\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<langchain_community.vectorstores.chroma.Chroma at 0x1fb746d02e0>"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print(\"向量化与存储索引\")\n",
    "#导入必须的包\n",
    "from langchain.document_loaders import UnstructuredExcelLoader,Docx2txtLoader,PyPDFLoader\n",
    "from langchain.text_splitter import  CharacterTextSplitter\n",
    "# from langchain_openai import OpenAIEmbeddings\n",
    "from langchain.embeddings import DashScopeEmbeddings\n",
    "from langchain.vectorstores import  Chroma\n",
    "import os\n",
    "\n",
    "# 设置阿里云API Key（从环境变量读取或直接设置）\n",
    "os.environ[\"DASHSCOPE_API_KEY\"] = \"sk-4e88cf4db3e14894bafaff606d296610\"  # 替换为你的实际Key\n",
    "\n",
    "#定义chatdoc\n",
    "class ChatDoc():\n",
    "    def __init__(self):\n",
    "        self.doc = None\n",
    "        self.splitText = [] #分割后的文本\n",
    "\n",
    "    def getFile(self):\n",
    "        doc = self.doc\n",
    "        loaders = {\n",
    "            \"docx\":Docx2txtLoader,\n",
    "            \"pdf\":PyPDFLoader,\n",
    "            \"xlsx\":UnstructuredExcelLoader,\n",
    "        }\n",
    "        file_extension = doc.split(\".\")[-1]\n",
    "        loader_class = loaders.get(file_extension)\n",
    "        if loader_class:\n",
    "            try:\n",
    "                loader = loader_class(doc)\n",
    "                text = loader.load()\n",
    "                return text\n",
    "            except Exception as e: \n",
    "                print(f\"Error loading {file_extension} files:{e}\") \n",
    "        else:\n",
    "             print(f\"Unsupported file extension: {file_extension}\")\n",
    "             return  None \n",
    "\n",
    "    #处理文档的函数\n",
    "    def splitSentences(self):\n",
    "        full_text = self.getFile() #获取文档内容\n",
    "        if full_text != None:\n",
    "            #对文档进行分割\n",
    "            text_split = CharacterTextSplitter(\n",
    "                chunk_size=150,\n",
    "                chunk_overlap=20,\n",
    "            )\n",
    "            texts = text_split.split_documents(full_text)\n",
    "            self.splitText = texts\n",
    "    \n",
    "    #向量化与向量存储\n",
    "    def embeddingAndVectorDB(self):\n",
    "        # embeddings = OpenAIEmbeddings()\n",
    "        embeddings = DashScopeEmbeddings(\n",
    "            model=\"text-embedding-v1\",  # 使用text-embedding-v1模型\n",
    "        )\n",
    "        db =Chroma.from_documents(\n",
    "            documents = self.splitText,\n",
    "            embedding = embeddings,\n",
    "        )\n",
    "        return db\n",
    "\n",
    "chat_doc = ChatDoc()\n",
    "chat_doc.doc = \"kecheng/example/fake.docx\"\n",
    "chat_doc.splitSentences()\n",
    "chat_doc.embeddingAndVectorDB()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "c28b4a91-1ba3-47da-afb2-c7e4f7e8f706",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "索引并使用自然语言找出相关的文本块\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[Document(metadata={'source': 'kecheng/example/fake.docx'}, page_content='报告撰写日期：2023年4月20日'),\n",
       " Document(metadata={'source': 'kecheng/example/fake.docx'}, page_content='报告撰写日期：2023年4月20日'),\n",
       " Document(metadata={'source': 'kecheng/example/fake.docx'}, page_content='报告撰写日期：2023年4月20日'),\n",
       " Document(metadata={'source': 'kecheng/example/fake.docx'}, page_content='4. 净利润：亏损人民币800万元，去年同期为盈利人民币200万元。\\n\\n5. 现金流量：公司现金流量紧张，现金及现金等价物余额为人民币500万元，难以支撑日常运营。\\n\\n6. 存货：存货积压严重，库存商品价值约为人民币400万元，大部分产品滞销。')]"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print(\"索引并使用自然语言找出相关的文本块\")\n",
    "#导入必须的包\n",
    "from langchain.document_loaders import UnstructuredExcelLoader,Docx2txtLoader,PyPDFLoader\n",
    "from langchain.text_splitter import  CharacterTextSplitter\n",
    "# from langchain_openai import OpenAIEmbeddings\n",
    "from langchain.vectorstores import  Chroma\n",
    "from langchain.embeddings import DashScopeEmbeddings\n",
    "import os\n",
    "\n",
    "# 设置阿里云API Key（从环境变量读取或直接设置）\n",
    "os.environ[\"DASHSCOPE_API_KEY\"] = \"sk-4e88cf4db3e14894bafaff606d296610\"  # 替换为你的实际Key\n",
    "\n",
    "#定义chatdoc\n",
    "class ChatDoc():\n",
    "    def __init__(self):\n",
    "        self.doc = None\n",
    "        self.splitText = [] #分割后的文本\n",
    "\n",
    "    def getFile(self):\n",
    "        doc = self.doc\n",
    "        loaders = {\n",
    "            \"docx\":Docx2txtLoader,\n",
    "            \"pdf\":PyPDFLoader,\n",
    "            \"xlsx\":UnstructuredExcelLoader,\n",
    "        }\n",
    "        file_extension = doc.split(\".\")[-1]\n",
    "        loader_class = loaders.get(file_extension)\n",
    "        if loader_class:\n",
    "            try:\n",
    "                loader = loader_class(doc)\n",
    "                text = loader.load()\n",
    "                return text\n",
    "            except Exception as e: \n",
    "                print(f\"Error loading {file_extension} files:{e}\") \n",
    "        else:\n",
    "             print(f\"Unsupported file extension: {file_extension}\")\n",
    "             return  None \n",
    "\n",
    "    #处理文档的函数\n",
    "    def splitSentences(self):\n",
    "        full_text = self.getFile() #获取文档内容\n",
    "        if full_text != None:\n",
    "            #对文档进行分割\n",
    "            text_split = CharacterTextSplitter(\n",
    "                chunk_size=150,\n",
    "                chunk_overlap=20,\n",
    "            )\n",
    "            texts = text_split.split_documents(full_text)\n",
    "            self.splitText = texts\n",
    "    \n",
    "    #向量化与向量存储\n",
    "    def embeddingAndVectorDB(self):\n",
    "        embeddings = DashScopeEmbeddings(\n",
    "            model=\"text-embedding-v1\",  # 使用text-embedding-v1模型\n",
    "        )\n",
    "        db =Chroma.from_documents(\n",
    "            documents = self.splitText,\n",
    "            embedding = embeddings,\n",
    "        )\n",
    "        return db\n",
    "    \n",
    "    #提问并找到相关的文本块\n",
    "    def askAndFindFiles(self,question):\n",
    "        db = self.embeddingAndVectorDB()\n",
    "        retriever = db.as_retriever()\n",
    "        results = retriever.invoke(question)\n",
    "        return results\n",
    "\n",
    "chat_doc = ChatDoc()\n",
    "chat_doc.doc = \"kecheng/example/fake.docx\"\n",
    "chat_doc.splitSentences()\n",
    "chat_doc.askAndFindFiles(\"这家公司叫什么名字?\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "2da93561-fdac-4211-a592-eaffbc10ab9a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "使用多重查询提高文档检索精确度\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:httpx:HTTP Request: POST https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions \"HTTP/1.1 200 OK\"\n",
      "INFO:langchain.retrievers.multi_query:Generated queries: ['公司名字叫什么？  ', '贵公司的全称是什么？  ', '请问公司的正式名称是？']\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[Document(metadata={'source': 'kecheng/example/fake.docx'}, page_content='报告撰写日期：2023年4月20日')]\n"
     ]
    }
   ],
   "source": [
    "print(\"使用多重查询提高文档检索精确度\")\n",
    "#导入必须的包\n",
    "from langchain.document_loaders import UnstructuredExcelLoader,Docx2txtLoader,PyPDFLoader\n",
    "from langchain.text_splitter import  CharacterTextSplitter\n",
    "# from langchain_openai import OpenAIEmbeddings\n",
    "from langchain.embeddings import DashScopeEmbeddings\n",
    "from langchain.vectorstores import  Chroma\n",
    "#引入openai和多重向量检索\n",
    "from langchain.chat_models import ChatOpenAI\n",
    "from langchain.retrievers.multi_query import MultiQueryRetriever\n",
    "#设置下logging查看生成查询\n",
    "import logging\n",
    "import os\n",
    "\n",
    "# 设置阿里云API Key（从环境变量读取或直接设置）\n",
    "os.environ[\"DASHSCOPE_API_KEY\"] = \"sk-4e88cf4db3e14894bafaff606d296610\"  # 替换为你的实际Key\n",
    "\n",
    "#定义chatdoc\n",
    "class ChatDoc():\n",
    "    def __init__(self):\n",
    "        self.doc = None\n",
    "        self.splitText = [] #分割后的文本\n",
    "\n",
    "    def getFile(self):\n",
    "        doc = self.doc\n",
    "        loaders = {\n",
    "            \"docx\":Docx2txtLoader,\n",
    "            \"pdf\":PyPDFLoader,\n",
    "            \"xlsx\":UnstructuredExcelLoader,\n",
    "        }\n",
    "        file_extension = doc.split(\".\")[-1]\n",
    "        loader_class = loaders.get(file_extension)\n",
    "        if loader_class:\n",
    "            try:\n",
    "                loader = loader_class(doc)\n",
    "                text = loader.load()\n",
    "                return text\n",
    "            except Exception as e: \n",
    "                print(f\"Error loading {file_extension} files:{e}\") \n",
    "        else:\n",
    "             print(f\"Unsupported file extension: {file_extension}\")\n",
    "             return  None \n",
    "\n",
    "    #处理文档的函数\n",
    "    def splitSentences(self):\n",
    "        full_text = self.getFile() #获取文档内容\n",
    "        if full_text != None:\n",
    "            #对文档进行分割\n",
    "            text_split = CharacterTextSplitter(\n",
    "                chunk_size=150,\n",
    "                chunk_overlap=20,\n",
    "            )\n",
    "            texts = text_split.split_documents(full_text)\n",
    "            self.splitText = texts\n",
    "    \n",
    "    #向量化与向量存储\n",
    "    def embeddingAndVectorDB(self):\n",
    "        embeddings = DashScopeEmbeddings(\n",
    "            model=\"text-embedding-v1\",  # 使用text-embedding-v1模型\n",
    "        )\n",
    "        db =Chroma.from_documents(\n",
    "            documents = self.splitText,\n",
    "            embedding = embeddings,\n",
    "        )\n",
    "        return db\n",
    "    \n",
    "    #提问并找到相关的文本块\n",
    "    def askAndFindFiles(self,question):\n",
    "        db = self.embeddingAndVectorDB()\n",
    "        #把问题交给LLM进行多角度的扩展\n",
    "        llm = ChatOpenAI(\n",
    "            model=\"qwen-plus\",  # 使用通义千问 plus 模型\n",
    "            openai_api_key=\"sk-4e88cf4db3e14894bafaff606d296610\",\n",
    "            openai_api_base=\"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n",
    "            temperature=0\n",
    "        )\n",
    "        retriever_from_llm = MultiQueryRetriever.from_llm(\n",
    "            retriever = db.as_retriever(),\n",
    "            llm = llm,\n",
    "        )\n",
    "        return retriever_from_llm.get_relevant_documents(question)\n",
    "\n",
    "chat_doc = ChatDoc()\n",
    "chat_doc.doc = \"kecheng/example/fake.docx\"\n",
    "chat_doc.splitSentences()\n",
    "\n",
    "logging.basicConfig(level=logging.INFO)\n",
    "logging.getLogger(\"langchain.retrievers.multi_query\").setLevel(logging.DEBUG)\n",
    "unique_doc = chat_doc.askAndFindFiles(\"公司名称是什么?\")\n",
    "print(unique_doc)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "601c935d-b3a2-4d3f-a263-80dfecc64741",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "使用上下文压缩检索降低冗余信息\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:httpx:HTTP Request: POST https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions \"HTTP/1.1 200 OK\"\n",
      "INFO:httpx:HTTP Request: POST https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions \"HTTP/1.1 200 OK\"\n",
      "INFO:httpx:HTTP Request: POST https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions \"HTTP/1.1 200 OK\"\n",
      "INFO:httpx:HTTP Request: POST https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions \"HTTP/1.1 200 OK\"\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "这间公司的负债有多少？\n",
      " [Document(metadata={'source': 'kecheng/example/fake.docx'}, page_content='现金流量：公司现金流量紧张，现金及现金等价物余额为人民币500万元，难以支撑日常运营。'), Document(metadata={'source': 'kecheng/example/fake.docx'}, page_content='现金流量：公司现金流量紧张，现金及现金等价物余额为人民币500万元，难以支撑日常运营。'), Document(metadata={'source': 'kecheng/example/fake.docx'}, page_content='难以支撑日常运营。'), Document(metadata={'source': 'kecheng/example/fake.docx'}, page_content='现金流量：公司现金流量紧张，现金及现金等价物余额为人民币500万元，难以支撑日常运营。')]\n"
     ]
    }
   ],
   "source": [
    "print(\"使用上下文压缩检索降低冗余信息\")\n",
    "#导入必须的包\n",
    "from langchain.document_loaders import UnstructuredExcelLoader,Docx2txtLoader,PyPDFLoader\n",
    "from langchain.text_splitter import  CharacterTextSplitter\n",
    "# from langchain_openai import OpenAIEmbeddings\n",
    "from langchain.embeddings import DashScopeEmbeddings\n",
    "from langchain.vectorstores import  Chroma\n",
    "#引入openai和多重向量检索\n",
    "#from langchain.chat_models import ChatOpenAI\n",
    "#from langchain.retrievers.multi_query import MultiQueryRetriever\n",
    "#引入上下文压缩相关包\n",
    "# from langchain.llms import  OpenAI\n",
    "from langchain_openai import ChatOpenAI\n",
    "from langchain.retrievers import ContextualCompressionRetriever\n",
    "from langchain.retrievers.document_compressors import  LLMChainExtractor\n",
    "#设置下logging查看生成查询\n",
    "import logging\n",
    "import os\n",
    "\n",
    "# 设置阿里云API Key（从环境变量读取或直接设置）\n",
    "os.environ[\"DASHSCOPE_API_KEY\"] = \"sk-4e88cf4db3e14894bafaff606d296610\"  # 替换为你的实际Key\n",
    "\n",
    "#定义chatdoc\n",
    "class ChatDoc():\n",
    "    def __init__(self):\n",
    "        self.doc = None\n",
    "        self.splitText = [] #分割后的文本\n",
    "\n",
    "    def getFile(self):\n",
    "        doc = self.doc\n",
    "        loaders = {\n",
    "            \"docx\":Docx2txtLoader,\n",
    "            \"pdf\":PyPDFLoader,\n",
    "            \"xlsx\":UnstructuredExcelLoader,\n",
    "        }\n",
    "        file_extension = doc.split(\".\")[-1]\n",
    "        loader_class = loaders.get(file_extension)\n",
    "        if loader_class:\n",
    "            try:\n",
    "                loader = loader_class(doc)\n",
    "                text = loader.load()\n",
    "                return text\n",
    "            except Exception as e: \n",
    "                print(f\"Error loading {file_extension} files:{e}\") \n",
    "        else:\n",
    "             print(f\"Unsupported file extension: {file_extension}\")\n",
    "             return  None \n",
    "\n",
    "    #处理文档的函数\n",
    "    def splitSentences(self):\n",
    "        full_text = self.getFile() #获取文档内容\n",
    "        if full_text != None:\n",
    "            #对文档进行分割\n",
    "            text_split = CharacterTextSplitter(\n",
    "                chunk_size=150,\n",
    "                chunk_overlap=20,\n",
    "            )\n",
    "            texts = text_split.split_documents(full_text)\n",
    "            self.splitText = texts\n",
    "    \n",
    "    #向量化与向量存储\n",
    "    def embeddingAndVectorDB(self):\n",
    "        embeddings = DashScopeEmbeddings(\n",
    "            model=\"text-embedding-v1\",  # 使用text-embedding-v1模型\n",
    "        )\n",
    "        db =Chroma.from_documents(\n",
    "            documents = self.splitText,\n",
    "            embedding = embeddings,\n",
    "        )\n",
    "        return db\n",
    "    \n",
    "    #提问并找到相关的文本块\n",
    "    def askAndFindFiles(self,question):\n",
    "        db = self.embeddingAndVectorDB()\n",
    "        retriever = db.as_retriever()\n",
    "        # llm = OpenAI(temperature=0)\n",
    "        llm = ChatOpenAI(\n",
    "            model=\"qwen-plus\",\n",
    "            openai_api_key=\"sk-4e88cf4db3e14894bafaff606d296610\",\n",
    "            openai_api_base=\"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n",
    "            temperature=0\n",
    "        )\n",
    "        compressor = LLMChainExtractor.from_llm(\n",
    "            llm = llm,\n",
    "        )\n",
    "        compressor_retriever = ContextualCompressionRetriever(\n",
    "            base_retriever = retriever,\n",
    "            base_compressor = compressor,\n",
    "        )\n",
    "        return compressor_retriever.get_relevant_documents(query=question)\n",
    "\n",
    "chat_doc = ChatDoc()\n",
    "chat_doc.doc = \"kecheng/example/fake.docx\"\n",
    "chat_doc.splitSentences()\n",
    "\n",
    "logging.basicConfig(level=logging.INFO)\n",
    "logging.getLogger(\"langchain.retrievers.multi_query\").setLevel(logging.DEBUG)\n",
    "unique_doc = chat_doc.askAndFindFiles(\"这间公司的负债有多少？\")\n",
    "print(\"这间公司的负债有多少？\\n\", unique_doc)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "ec54e3ff-db01-4c8e-bab6-4f1e44d477a7",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "在向量存储里使用最大边际相似性（MMR）和相似性打分\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "D:\\conda_envs\\rag_learn\\lib\\site-packages\\langchain_core\\vectorstores\\base.py:1083: UserWarning: Relevance scores must be between 0 and 1, got [(Document(metadata={'source': 'kecheng/example/fake.docx'}, page_content='一、公司基本信息\\n\\n名称：宏图科技发展有限公司\\n\\n注册地址：江苏省南京市雨花台区软件大道101号\\n\\n成立日期：2011年5月16日\\n\\n法定代表人：李强\\n\\n注册资本：人民币5000万元\\n\\n员工人数：约200人\\n\\n联系电话：025-88888888\\n\\n电子邮箱：info@hongtutech.cn'), -7066.137983064955)]\n",
      "  self.vectorstore.similarity_search_with_relevance_scores(\n",
      "WARNING:langchain_core.vectorstores.base:No relevant docs were retrieved using the relevance score threshold 0.1\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[]\n"
     ]
    }
   ],
   "source": [
    "print(\"在向量存储里使用最大边际相似性（MMR）和相似性打分\")\n",
    "#导入必须的包\n",
    "from langchain.document_loaders import UnstructuredExcelLoader,Docx2txtLoader,PyPDFLoader\n",
    "from langchain.text_splitter import  CharacterTextSplitter\n",
    "# from langchain_openai import OpenAIEmbeddings\n",
    "from langchain.embeddings import DashScopeEmbeddings\n",
    "from langchain.vectorstores import  Chroma\n",
    "#设置下logging查看生成查询\n",
    "import logging\n",
    "import os\n",
    "\n",
    "# 设置阿里云API Key（从环境变量读取或直接设置）\n",
    "os.environ[\"DASHSCOPE_API_KEY\"] = \"sk-4e88cf4db3e14894bafaff606d296610\"  # 替换为你的实际Key\n",
    "\n",
    "\n",
    "#定义chatdoc\n",
    "class ChatDoc():\n",
    "    def __init__(self):\n",
    "        self.doc = None\n",
    "        self.splitText = [] #分割后的文本\n",
    "\n",
    "    def getFile(self):\n",
    "        doc = self.doc\n",
    "        loaders = {\n",
    "            \"docx\":Docx2txtLoader,\n",
    "            \"pdf\":PyPDFLoader,\n",
    "            \"xlsx\":UnstructuredExcelLoader,\n",
    "        }\n",
    "        file_extension = doc.split(\".\")[-1]\n",
    "        loader_class = loaders.get(file_extension)\n",
    "        if loader_class:\n",
    "            try:\n",
    "                loader = loader_class(doc)\n",
    "                text = loader.load()\n",
    "                return text\n",
    "            except Exception as e: \n",
    "                print(f\"Error loading {file_extension} files:{e}\") \n",
    "        else:\n",
    "             print(f\"Unsupported file extension: {file_extension}\")\n",
    "             return  None \n",
    "\n",
    "    #处理文档的函数\n",
    "    def splitSentences(self):\n",
    "        full_text = self.getFile() #获取文档内容\n",
    "        if full_text != None:\n",
    "            #对文档进行分割\n",
    "            text_split = CharacterTextSplitter(\n",
    "                chunk_size=150,\n",
    "                chunk_overlap=20,\n",
    "            )\n",
    "            texts = text_split.split_documents(full_text)\n",
    "            self.splitText = texts\n",
    "    \n",
    "    #向量化与向量存储\n",
    "    def embeddingAndVectorDB(self):\n",
    "        embeddings = DashScopeEmbeddings(\n",
    "            model=\"text-embedding-v1\",  # 使用text-embedding-v1模型\n",
    "        )\n",
    "        db =Chroma.from_documents(\n",
    "            documents = self.splitText,\n",
    "            embedding = embeddings,\n",
    "        )\n",
    "        return db\n",
    "    \n",
    "    #提问并找到相关的文本块\n",
    "    def askAndFindFiles(self,question):\n",
    "        db = self.embeddingAndVectorDB()\n",
    "        #retriever = db.as_retriever(search_type=\"mmr\")\n",
    "        retriever = db.as_retriever(search_type=\"similarity_score_threshold\",search_kwargs={\"score_threshold\":.1,\"k\":1})\n",
    "        return retriever.get_relevant_documents(query=question)\n",
    "        \n",
    "\n",
    "chat_doc = ChatDoc()\n",
    "chat_doc.doc = \"kecheng/example/fake.docx\"\n",
    "chat_doc.splitSentences()\n",
    "\n",
    "logging.basicConfig(level=logging.INFO)\n",
    "logging.getLogger(\"langchain.retrievers.multi_query\").setLevel(logging.DEBUG)\n",
    "unique_doc = chat_doc.askAndFindFiles(\"这家公司的地址在哪里?\")\n",
    "print(unique_doc)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "a28fcf1a-beec-408f-8834-9feda2f7d205",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "ChatDOc:和文件聊天\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "D:\\conda_envs\\rag_learn\\lib\\site-packages\\langchain_core\\vectorstores\\base.py:1083: UserWarning: Relevance scores must be between 0 and 1, got [(Document(metadata={'source': 'kecheng/example/fake.docx'}, page_content='报告撰写日期：2023年4月20日'), -9349.165499181161)]\n",
      "  self.vectorstore.similarity_search_with_relevance_scores(\n",
      "WARNING:langchain_core.vectorstores.base:No relevant docs were retrieved using the relevance score threshold 0.5\n",
      "INFO:httpx:HTTP Request: POST https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions \"HTTP/1.1 200 OK\"\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "AIMessage(content='公司注册地址是上海市浦东新区世纪大道100号。', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 14, 'prompt_tokens': 71, 'total_tokens': 85, 'completion_tokens_details': None, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}}, 'model_name': 'qwen-plus', 'system_fingerprint': None, 'id': 'chatcmpl-7a17e1f0-8815-9ed1-99e8-51d69da87d50', 'service_tier': None, 'finish_reason': 'stop', 'logprobs': None}, id='run--8014a465-ed8f-48d7-98b4-875e73d6abb6-0', usage_metadata={'input_tokens': 71, 'output_tokens': 14, 'total_tokens': 85, 'input_token_details': {'cache_read': 0}, 'output_token_details': {}})"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print(\"ChatDOc:和文件聊天\")\n",
    "#导入必须的包\n",
    "from langchain.document_loaders import UnstructuredExcelLoader,Docx2txtLoader,PyPDFLoader\n",
    "from langchain.text_splitter import  CharacterTextSplitter\n",
    "# from langchain.embeddings import  OpenAIEmbeddings\n",
    "from langchain.embeddings import DashScopeEmbeddings\n",
    "from langchain.vectorstores import  Chroma\n",
    "#导入聊天所需的模块\n",
    "# from langchain.chat_models import ChatOpenAI\n",
    "from langchain_openai import ChatOpenAI\n",
    "from langchain.prompts import ChatPromptTemplate\n",
    "import os\n",
    "\n",
    "# 设置阿里云API Key（从环境变量读取或直接设置）\n",
    "os.environ[\"DASHSCOPE_API_KEY\"] = \"sk-4e88cf4db3e14894bafaff606d296610\"  # 替换为你的实际Key\n",
    "\n",
    "#定义chatdoc\n",
    "class ChatDoc():\n",
    "    def __init__(self):\n",
    "        self.doc = None\n",
    "        self.splitText = [] #分割后的文本\n",
    "        self.template = [\n",
    "            (\"system\",\"你是一个处理文档的秘书,你从不说自己是一个大模型或者AI助手,你会根据下面提供的上下文内容来继续回答问题.\\n 上下文内容\\n {context} \\n\"),\n",
    "            (\"human\",\"你好！\"),\n",
    "            (\"ai\",\"你好\"),\n",
    "            (\"human\",\"{question}\"),\n",
    "        ]\n",
    "        self.prompt = ChatPromptTemplate.from_messages(self.template)\n",
    "\n",
    "    def getFile(self):\n",
    "        doc = self.doc\n",
    "        loaders = {\n",
    "            \"docx\":Docx2txtLoader,\n",
    "            \"pdf\":PyPDFLoader,\n",
    "            \"xlsx\":UnstructuredExcelLoader,\n",
    "        }\n",
    "        file_extension = doc.split(\".\")[-1]\n",
    "        loader_class = loaders.get(file_extension)\n",
    "        if loader_class:\n",
    "            try:\n",
    "                loader = loader_class(doc)\n",
    "                text = loader.load()\n",
    "                return text\n",
    "            except Exception as e: \n",
    "                print(f\"Error loading {file_extension} files:{e}\") \n",
    "        else:\n",
    "             print(f\"Unsupported file extension: {file_extension}\")\n",
    "             return  None \n",
    "\n",
    "    #处理文档的函数\n",
    "    def splitSentences(self):\n",
    "        full_text = self.getFile() #获取文档内容\n",
    "        if full_text != None:\n",
    "            #对文档进行分割\n",
    "            text_split = CharacterTextSplitter(\n",
    "                chunk_size=150,\n",
    "                chunk_overlap=20,\n",
    "            )\n",
    "            texts = text_split.split_documents(full_text)\n",
    "            self.splitText = texts\n",
    "    \n",
    "    #向量化与向量存储\n",
    "    def embeddingAndVectorDB(self):\n",
    "        # embeddings = OpenAIEmbeddings()\n",
    "        embeddings = DashScopeEmbeddings(\n",
    "            model=\"text-embedding-v1\",  # 使用text-embedding-v1模型\n",
    "        )\n",
    "        db =Chroma.from_documents(\n",
    "            documents = self.splitText,\n",
    "            embedding = embeddings,\n",
    "        )\n",
    "        return db\n",
    "    \n",
    "    #提问并找到相关的文本块\n",
    "    def askAndFindFiles(self,question):\n",
    "        db = self.embeddingAndVectorDB()\n",
    "        #retriever = db.as_retriever(search_type=\"mmr\")\n",
    "        retriever = db.as_retriever(search_type=\"similarity_score_threshold\",search_kwargs={\"score_threshold\":.5,\"k\":1})\n",
    "        return retriever.get_relevant_documents(query=question)\n",
    "    \n",
    "    #用自然语言和文档聊天\n",
    "    def chatWithDoc(self,question):\n",
    "        _content = \"\"\n",
    "        context = self.askAndFindFiles(question)\n",
    "        for i in context:\n",
    "            _content += i.page_content\n",
    "        \n",
    "        messages = self.prompt.format_messages(context=_content,question=question)\n",
    "        chat = ChatOpenAI(\n",
    "            model=\"qwen-plus\",\n",
    "            openai_api_key=\"sk-4e88cf4db3e14894bafaff606d296610\",\n",
    "            openai_api_base=\"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n",
    "            temperature=0\n",
    "        )\n",
    "        return chat.invoke(messages)\n",
    "\n",
    "chat_doc = ChatDoc()\n",
    "chat_doc.doc = \"kecheng/example/fake.docx\"\n",
    "chat_doc.splitSentences()\n",
    "chat_doc.chatWithDoc(\"公司注册地址是哪里？\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3021e0ba-4cb7-4eec-8095-df388d96953f",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "rag_learn",
   "language": "python",
   "name": "rag_learn"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
